
function Get-Parameters {
    [CmdletBinding()]
    [OutputType('Parameters')]
    param (
        [Parameter(Mandatory = $false)][Parameters]$Parameters,
        [Parameter(Mandatory = $false)][switch]$ConfirmAll
    )
    DynamicParam {
        <# Add Overwrite parameter #>
        $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
        # Create a new overwriteAttribute Object.
        $overwriteAttribute = New-Object System.Management.Automation.ParameterAttribute
        $overwriteAttribute.Mandatory = $false
        $overwriteAttribute.HelpMessage = "Updates the 'Parameters' object's values whenever you select something else."
        # Create an attribute collection object for the attribute we just created.
        $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
        # Add overwriteAttribute to the collection.
        $attributeCollection.Add($overwriteAttribute)

        if ($PSBoundParameters.ContainsKey('Parameters')) {
            # Create a switch parameter called 'Overwrite'.
            $Overwrite = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Overwrite", [Switch], $attributeCollection)
            # Expose the name of our parameter.
            $paramDictionary.Add('Overwrite', $Overwrite)
            return $paramDictionary
        }
        <#
            NOTE:
            The user won't see the dynamic parameter.
            It has something to do with $Parameters being of a custom type.
            The dynamic parameter works though as intended.
        #>
    }
    process {
        # Create 'Parameters' object if not provided by user.
        if (!$Parameters) {
            $Parameters = (New-LSParameters)
        }
        
        # Clone the input parameter if the user doesn't want to overwrite it.
        if (!$PSBoundParameters.Overwrite) {
            $Parameters = $Parameters.Clone()
        }

        $Parameters.ConfirmAll = $ConfirmAll

        # Create project folder if needed.
        if (!$Parameters.LSInsight.ProjectFolder) {
            $Parameters.LSInsight.ProjectFolder = New-ProjectFolder
        }

        # Create path to a file where the parameters object will be stored.
        if (!$Parameters.LSInsight.ParametersOutFilePath) {
            $Parameters.LSInsight.ParametersOutFilePath = Join-Path $Parameters.LSInsight.ProjectFolder -ChildPath 'Parameters.json'
        }

        Get-AzureParameters -Parameters $Parameters | Out-Null
        
        Get-CentralParameters -Parameters $Parameters | Out-Null

        Get-InsightParameters -Parameters $Parameters | Out-Null
        
        return $Parameters
    }

    <#
    .SYNOPSIS
        Gathers deployment information from user.
    .DESCRIPTION
        The Get-Parameters function gathers necessary information from the user, necessary for the LS Insight deployment.
        
        This function asks for basic Azure information as well as LS Central and LS Insight information.

        This function validates the information provided to some extent.
    .EXAMPLE
        PS C:\> $Params = Get-Parameters
        PS C:\> $Params

        LSCentral           LSInsight           Azure           ConfirmAll
        ---------           ---------           -----           ----------
        LSCentralParameters LSInsightParameters AzureParameters      False

        This is the most basic usage.
        The function asks for all the relevant information and returns a 'Parameters' object describing a LS Insight deployment.
    .Example
        PS C:\> $Params2 = Get-Parameters -Parameters $Params1
        PS C:\> $Params2

        LSCentral           LSInsight           Azure           ConfirmAll
        ---------           ---------           -----           ----------
        LSCentralParameters LSInsightParameters AzureParameters      False

        Every question will have a default answer based on the values found in the $Params1 object.
        The user is asked to confirm every default answer or whether he wants to change it.
        Passwords cannot have default values.
    .Example
        PS C:\> $Params2 = Get-Parameters -Parameters $Params1 -ConfirmAll
        PS C:\> $Params2

        LSCentral           LSInsight           Azure           ConfirmAll
        ---------           ---------           -----           ----------
        LSCentralParameters LSInsightParameters AzureParameters      True

        Every default answer supplied by $Params1 object is automatically confirmed.
        The user is only asked for missing information not provided in $Params1.
        Passwords cannot have default values.
    .Example
        PS C:\> Get-Parameters -Parameters $Params -Overwrite

        LSCentral           LSInsight           Azure           ConfirmAll
        ---------           ---------           -----           ----------
        LSCentralParameters LSInsightParameters AzureParameters      False

        Every question will have a default answer based on the values found in the $Params object.
        The user is asked to confirm every default answer or whether he wants to change it.
        If the user chooses to provide an answer different from the default answer, the $Params object will store that change.
        Passwords cannot have default values.
    .Example
        PS C:\> $Params = New-Parameters
        PS C:\> Get-Parameters -Parameters $Params -Overwrite -ConfirmAll
        PS C:\> $Params

        LSCentral           LSInsight           Azure           ConfirmAll
        ---------           ---------           -----           ----------
        LSCentralParameters LSInsightParameters AzureParameters      True

        By overwriting the $Params object as each question is asked, it's possible to stop and start the function without losing the progress.
        By using the '-ConfirmAll' parameter the user doesn't have to confirm every answer already given, and instead resume where he stopped the function. 
    .INPUTS
        None. You cannot pipe objects to Get-Parameters.
    .OUTPUTS
        Parameters. Get-Parameters returns an LS Insight deployment parameter object.
    .PARAMETER Parameters
        A 'Parameters' type object that is used to provide default answers to every question.
        Required?                    false
        Position?                    
        Default value                New 'Parameters' object.
        Accept pipeline input?       false
        Accept wildcard characters?  false
    .PARAMETER ConfirmAll
        Switch. Accepts every default answer provided by the '-Parameters' parameter.
        Instead of asking user to confirm each default answer.
        Required?                    false
        Position?                    
        Default value                
        Accept pipeline input?       false
        Accept wildcard characters?  false
    .PARAMETER Overwrite
        Switch. Makes sure that the '-Parameter' parameter object is overwritten whenever the user provides a different answer than the default answer.
        '-Parameters' parameter must be used.
        Required?                    false
        Position?                    
        Default value                
        Accept pipeline input?       false
        Accept wildcard characters?  false
    #>
}